
import { CreateTableInfoDto, UpdateTableInfoDto, QueryTableInfoDto, DeleteTableInfoDto, SelectOneTableInfoDto, CreateCodeTableInfoDto } from '@/dto/tableInfo.dto';
import { FieldInfo } from '@/entities/fieldInfo.entity';
import tableInfoRepository from '@/repositories/tableInfo.repository';
import { EntityManager, FindOneOptions, In } from 'typeorm';
import { AppDataSource } from '@/config/AppDataSource';
import { TableInfo } from '@/entities/tableInfo.entity';
import { IndexInfo } from '@/entities/indexInfo.entity';
import path from 'path';
import fs from 'fs';
import createEntityCode from './helper/createEntityCode';
import createDtoFile from './helper/createDtoFile';
import createRouterCode from './helper/createRouterCode';
import createControllersFile from './helper/createControllersFile';
import createServicesFile from './helper/createServicesFile';
import createPageListCode from './helper/createPageListCode';
import createWebApiCode from './helper/createWebApiCode';
import createEditModalCode from './helper/createEditModalCode';


class TableInfoService {
    manager = AppDataSource.manager

    /**
     * 创建
     * @param data  
     * @returns 
     */

    async add(data: CreateTableInfoDto) {
        // 检查是否已存在
        const findOne = await this.manager.findOne(TableInfo, {
            where: [
                { name: data.name },
            ],
        })
        if (findOne) {
            if (findOne.name == data.name) {
                throw new Error('数据表名称已存在！');
            }

        }
        // 创建
        return this.manager.transaction(async (entityManager) => {
            const { fieldInfoList = [], indexInfoList = [] } = data;

            const tableInfo = new TableInfo();

            tableInfo.status = data.status;
            tableInfo.comment = data.comment;
            tableInfo.name = data.name;
            tableInfo.templateType = data.templateType;
            tableInfo.subTable = data.subTable;

            const result = await entityManager.save(tableInfo)
            console.log("result", result)
            // 2. 处理索引信息差异更新
            await this.handleIndexInfos(
                entityManager,
                tableInfo.id,
                indexInfoList
            );

            // 3. 处理字段信息差异更新
            await this.handleFieldInfos(
                entityManager,
                tableInfo.id,
                fieldInfoList
            );



            return result;



        })



    }
    async update(data: UpdateTableInfoDto) {
        const { fieldInfoList = [], indexInfoList = [], ...tableInfo } = data;


        // 1. 检查是否存在
        const existingCategory = await this.manager.findOne(TableInfo, {
            where: { id: data.id },
        })
        if (!existingCategory) {
            throw new Error("数据不存在")
        }


        const findOne = await this.manager
            .createQueryBuilder(TableInfo, 'tableInfo')
            .where('tableInfo.id != :id', { id: data.id })
            .andWhere('(tableInfo.name = :name)', { name: data.name })
            .getOne();
        if (findOne) {
            if (findOne.name == data.name) {
                throw new Error('名称已存在！');
            }

        }
        return this.manager.transaction(async (entityManager) => {
            await entityManager.update(
                TableInfo,
                tableInfo.id,
                {
                    comment: tableInfo.comment,
                    name: tableInfo.name,
                    status: tableInfo.status,
                    templateType: tableInfo.templateType,
                    subTable: tableInfo.subTable
                }
            );
            // 2. 处理索引信息差异更新
            await this.handleIndexInfos(
                entityManager,
                tableInfo.id,
                indexInfoList
            );

            // 3. 处理字段信息差异更新
            await this.handleFieldInfos(
                entityManager,
                tableInfo.id,
                fieldInfoList
            );
        })

    }
    /**
     * 处理更新字段信息
     * @param manager 
     * @param parentId 
     * @param fieldInfoList 
     */
    private async handleFieldInfos(
        manager: EntityManager,
        parentId: number,
        fieldInfoList: any[]
    ) {
        const submittedFields = fieldInfoList;

        // 1. 获取数据库中现有的 parentId=1 的所有字段
        const existingFields = await manager.find(FieldInfo, { where: { parentId } });

        // 2. 分类处理：找出需要新增、更新和删除的记录
        const submittedIds = new Set(submittedFields.map(f => f.id));
        const existingIds = new Set(existingFields.map(f => f.id));

        // 需要删除的字段（存在于数据库但不在提交数据中）
        const toDelete = existingFields.filter(f => !submittedIds.has(f.id));

        // 需要新增的字段（没有id或id不在现有数据中）
        const toCreate = submittedFields.filter(f => !f.id || !existingIds.has(f.id));

        // 需要更新的字段（id存在于现有数据中）
        const toUpdate = submittedFields.filter(f => f.id && existingIds.has(f.id));

        // 删除操作
        if (toDelete.length > 0) {
            await manager.remove(FieldInfo, toDelete);
        }

        // 新增操作
        if (toCreate.length > 0) {
            // 设置parentId并移除可能的id（如果是部分提交的数据）
            const fieldsToSave = toCreate.map(f => {
                const { id, ...rest } = f;
                return { ...rest, parentId };
            });
            await manager.save(FieldInfo, fieldsToSave);
        }

        // 更新操作
        if (toUpdate.length > 0) {
            // 只更新允许修改的字段，防止覆盖createdAt等字段
            const updatePromises = toUpdate.map(async field => {
                const { id, createdAt, updatedAt, ...updateData } = field;
                await manager.update(
                    FieldInfo,
                    { id, parentId },
                    { ...updateData, updatedAt: () => 'CURRENT_TIMESTAMP' }
                );
            });
            await Promise.all(updatePromises);
        }
    }


    private async handleIndexInfos(
        manager: EntityManager,
        parentId: number,
        fieldInfoList: any[]
    ) {
        const submittedFields = fieldInfoList;

        // 1. 获取数据库中现有的 parentId=1 的所有字段
        const existingFields = await manager.find(IndexInfo, { where: { parentId } });

        // 2. 分类处理：找出需要新增、更新和删除的记录
        const submittedIds = new Set(submittedFields.map(f => f.id));
        const existingIds = new Set(existingFields.map(f => f.id));

        // 需要删除的字段（存在于数据库但不在提交数据中）
        const toDelete = existingFields.filter(f => !submittedIds.has(f.id));

        // 需要新增的字段（没有id或id不在现有数据中）
        const toCreate = submittedFields.filter(f => !f.id || !existingIds.has(f.id));

        // 需要更新的字段（id存在于现有数据中）
        const toUpdate = submittedFields.filter(f => f.id && existingIds.has(f.id));

        // 删除操作
        if (toDelete.length > 0) {
            await manager.remove(IndexInfo, toDelete);
        }

        // 新增操作
        if (toCreate.length > 0) {
            // 设置parentId并移除可能的id（如果是部分提交的数据）
            const fieldsToSave = toCreate.map(f => {
                const { id, ...rest } = f;
                return { ...rest, parentId };
            });
            await manager.save(IndexInfo, fieldsToSave);
        }

        // 更新操作
        if (toUpdate.length > 0) {
            // 只更新允许修改的字段，防止覆盖createdAt等字段
            const updatePromises = toUpdate.map(async field => {
                const { id, createdAt, updatedAt, ...updateData } = field;
                await manager.update(
                    IndexInfo,
                    { id, parentId },
                    { ...updateData, updatedAt: () => 'CURRENT_TIMESTAMP' }
                );
            });
            await Promise.all(updatePromises);
        }
    }

    /** */

    async selectOne(reqData: SelectOneTableInfoDto) {
        const q: FindOneOptions<TableInfo> = {
            where: { id: reqData.id },
            relations: ['indexInfoList', 'fieldInfoList'],
            order: {
                indexInfoList: { id: 'ASC' },
                fieldInfoList: { id: 'ASC' }
            }
        }
        const item = await this.manager.findOne(TableInfo, q) as TableInfo

        return item;


    }

    async selectList(reqData: QueryTableInfoDto) {
        const { page, pageSize, name, orderBy, comment, status, fromDate, toDate } = reqData;

        const queryBuilder = this.manager
            .createQueryBuilder(TableInfo, 'tableInfo')
            .select([

                'tableInfo.id',
                'tableInfo.createdAt',
                'tableInfo.updatedAt',
                'tableInfo.status',
                'tableInfo.comment',
                'tableInfo.name',
                'tableInfo.templateType',
                'tableInfo.subTable'
            ]);

        if (name) {
            queryBuilder.andWhere('tableInfo.name LIKE :name', { name: `%${name}%` });
        }
        if (comment) {
            queryBuilder.andWhere('tableInfo.comment LIKE :comment', { comment: `%${comment}%` });
        }
        if (status) {
            queryBuilder.andWhere('tableInfo.status = :status', { status });
        }
        // 添加创建日期范围查询
        if (fromDate && toDate) {
            queryBuilder.andWhere('tableInfo.createdAt BETWEEN :fromDate AND :toDate', {
                fromDate: new Date(fromDate),
                toDate: new Date(`${toDate}T23:59:59.999Z`)

            });
        } else if (fromDate) {
            queryBuilder.andWhere('tableInfo.createdAt >= :fromDate', {
                fromDate: new Date(fromDate)
            });
        } else if (toDate) {
            queryBuilder.andWhere('tableInfo.createdAt <= :toDate', {
                toDate: new Date(`${toDate}T23:59:59.999Z`)

            });
        }
        const [sortBy, sortOrder] = orderBy.split(" ")
        const [tableInfo, total] = await queryBuilder
            .orderBy(`tableInfo.${sortBy}`, sortOrder.toLocaleUpperCase() as "ASC" | "DESC")
            .skip((page - 1) * pageSize)
            .take(pageSize)
            .getManyAndCount();
        return {
            list: tableInfo,
            total,
            page,
            pageSize,
            totalPages: Math.ceil(total / pageSize),
        };


    }
    async delete(reqData: DeleteTableInfoDto) {
        let res = await this.manager.delete(TableInfo, {
            id: In(reqData.ids)
        });
        if (!res) {
            throw new Error("id不存在，无删除记录！")
        }
        return res;


    }

    async createCode(req: CreateCodeTableInfoDto) {
        const res = await this.selectOne(req)

        res.fieldInfoList.forEach(item => {
            item.smallHumpCode = item.code.replace(/_(.)/g, (a: string, b: string) => `${b.toLocaleUpperCase()}`);
        })
        res.indexInfoList.forEach(item => {
            item.smallHumpCode = item.filedName.split(",").map(j => j.replace(/_(.)/g, (a: string, b: string) => `${b.toLocaleUpperCase()}`)).join(',')

        })

        let entityStr = await createEntityCode(res)
        let dtoStr = await createDtoFile(res)
        let routerStr = await createRouterCode(res)
        let controllersStr = await createControllersFile(res)
        let servicesStr = await createServicesFile(res)
        let pageListCodeStr = createPageListCode(res)
        let webApiCodeStr = createWebApiCode(res)
        let editModalCodeStr = createEditModalCode(res)

        return { ...res, entityStr, dtoStr, routerStr, controllersStr, servicesStr, pageListCodeStr, webApiCodeStr, editModalCodeStr } as any;

    }

}

export default new TableInfoService();

